home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1999 April / macformat-075.iso / Resources / Anti-virus / AntiGax 1.3 / Source / Antigax.c next >
Encoding:
C/C++ Source or Header  |  1998-10-10  |  11.7 KB  |  588 lines  |  [TEXT/CWIE]

  1. #include <ICAPI.h>
  2.  
  3.  
  4. void LogoUpdate(void);
  5. void LogoRefresh(char saveco);
  6. void RecurseDirectory(short vref, long did);
  7. typedef Boolean (*RecurseFunc)(void);
  8. Boolean CheckAppDirProc(void);
  9. Boolean CheckAppNodeProc(void);
  10. Boolean CheckINITNodeProc(void);
  11.  
  12. void WriteAppPath(void);
  13. pascal Boolean AlertKludge(DialogPtr theDialog, EventRecord *theEvent, short *itemHit);
  14. void DecodeVirus(void);
  15.  
  16. char RepairApp(short rev);
  17. Boolean DamagedApp(short rev);
  18. void WriteString(short fie, uchar *str);
  19.  
  20.  
  21. #define ntt 6
  22.  
  23. uchar        *agaxURL="\phttp://www.cse.unsw.edu.au/~s2191331/antigax/antigax.html";
  24.  
  25. RecurseFunc    recurseNodeProc,    recurseDirProc;
  26.  
  27. Handle        filnh,    dirnh,    volnh,    numh,    toth;
  28. DialogPtr    logo;
  29. FSSpec        *lantana;
  30. Ptr            bigstak;
  31. Str63        volnm;
  32. Str15        nums,    tots;
  33. OSType        targType[ntt]={'APPL','APPE','APPC','cdev','appe','INIT'};
  34. long        numo,    toto,    upi,    ufi;
  35. short        orrez,    logef;
  36. Boolean        hit_but,    check_only,    lmdco,    prevent_moves;
  37.  
  38. void main(void)
  39. {
  40. ModalFilterUPP        alk;
  41. StandardFileReply    rep;
  42. Str255                prognosis;
  43. short                chx;
  44.  
  45. InitGraf(&thePort);
  46. InitFonts();
  47. InitWindows();
  48. InitMenus();
  49. TEInit();
  50. InitDialogs(nil);
  51.  
  52. orrez=CurResFile();
  53. alk=NewModalFilterProc(AlertKludge);
  54.  
  55. bigstak=NewPtr(32768);    // we're going to tax the conventional stack enough later...
  56.  
  57. //DecodeVirus();
  58.  
  59. Rechoice:
  60.  
  61. numo=0;
  62. toto=0;
  63. upi=0;
  64. ufi=0;
  65. hit_but=0;
  66. lmdco=check_only=0;
  67. prevent_moves=0;
  68. logef=0;
  69.  
  70. chx=Alert(128,alk);
  71. if(chx==1) ExitToShell();
  72. if(chx==5)
  73.     {
  74.     ICInstance    iccy;
  75.     long        sst,    snd;
  76.     
  77.     sst=0;
  78.     snd=agaxURL[0];
  79.     
  80.     ICStart(&iccy,'Agax');
  81.     ICFindConfigFile(iccy,0,nil);
  82.     ICLaunchURL(iccy,nil,(char*)agaxURL+1,snd,&sst,&snd);
  83.     ICStop(iccy);
  84.     ExitToShell();
  85.     }
  86.  
  87. check_only=lmdco;
  88.  
  89. if(chx==2)    // Repair One File
  90.     {
  91.     short                rrf;
  92.     
  93.     StandardGetFile(nil,-1,targType,&rep);    // -1 used to be ntt
  94.     if(rep.sfGood)
  95.         {
  96.         rrf=FSpOpenResFile(&rep.sfFile,check_only?fsRdPerm:fsRdWrPerm);
  97.         if(!rrf || rrf==-1) Alert(129,nil);
  98.         else
  99.             {
  100.             Str255    filebit;
  101.             short    selk;
  102.             
  103.             lantana=&rep.sfFile;
  104.             
  105.             numo=RepairApp(rrf);
  106.             if(!numo && DamagedApp(rrf)) numo=2;
  107.             CloseResFile(rrf);
  108.             
  109.             selk=((numo+1)<<1) + (check_only?1:0);
  110.             GetIndString(prognosis,128,selk + 1);
  111.             GetIndString(filebit,129,selk + 1);
  112.             ParamText(lantana->name,prognosis,filebit,nil);
  113.             Alert(130,nil);
  114.             }
  115.         }
  116.     
  117.     goto Rechoice;
  118.     }
  119. else if(chx==3)    // Repair All Volumes
  120.     {
  121.     VCB            *queze;
  122.     
  123.     StandardPutFile(
  124.         check_only?"\pLog infected files in:":"\pOptionally log repaired files in:",
  125.         check_only?"\pInfected file log":"\pRepaired file log",
  126.         &rep);
  127.     if(rep.sfGood)
  128.         {
  129.         if(rep.sfReplacing) FSpDelete(&rep.sfFile);
  130.         FSpCreate(&rep.sfFile,'ttxt','TEXT',rep.sfScript);
  131.         FSpOpenDF(&rep.sfFile,fsWrPerm,&logef);
  132.         if(!logef || logef==-1)
  133.             {
  134.             SysBeep(20);
  135.             goto Rechoice;
  136.             }
  137.         WriteString(logef,
  138.             check_only?"\pInfected file list:\r":"\pRepaired file list:\r"
  139.             );
  140.         }
  141.     else
  142.         {
  143.         if(check_only) goto Rechoice;    // no pt searching if not writing it down!
  144.         logef=0;
  145.         }
  146.     
  147.     recurseNodeProc=CheckAppNodeProc;
  148.     recurseDirProc=CheckAppDirProc;
  149.     
  150.     ParamText(check_only?"\pinfected":"\prepaired",nil,nil,nil);
  151.     logo=GetNewDialog(256,nil,(WindowPtr)-1);
  152.     SetPort(logo);
  153.     
  154.     GetDialogItem(logo,2,nil,&volnh,nil);
  155.     GetDialogItem(logo,3,nil,&dirnh,nil);
  156.     GetDialogItem(logo,4,nil,&filnh,nil);
  157.     GetDialogItem(logo,5,nil,&numh,nil);
  158.     GetDialogItem(logo,6,nil,&toth,nil);
  159.     
  160.     ShowWindow(logo);
  161.     DrawDialog(logo);
  162.     
  163.     for(queze=(VCB*)(GetVCBQHdr()->qHead);queze;queze=(VCB*)queze->qLink)
  164.         {
  165.         if(check_only)
  166.             {
  167.             // Don't bother if it's software or hardware locked
  168.             if((queze->vcbAtrb&0x8000) || (queze->vcbAtrb&0x0080)) continue;
  169.             }
  170.         
  171.         BlockMoveData(queze->vcbVN,volnm,28);
  172.         SetDialogItemText(volnh,volnm);
  173.         SetDialogItemText(dirnh,"\p<root>");
  174.         
  175.         RecurseDirectory(queze->vcbVRefNum,fsRtDirID);
  176.         
  177.         if(hit_but) break;
  178.         }
  179.     
  180.     if(logef)
  181.         {
  182.         WriteString(logef,"\pEnd of list\r");
  183.         FSClose(logef);
  184.         }
  185.     
  186.     NumToString(toto,tots);        // numo will always be up-to-date
  187.     SetDialogItemText(toth,tots);
  188.     
  189.     GetDialogItem(logo,7,nil,&toth,nil);
  190.     SetDialogItemText(toth,hit_but?"\pCancelled - Click to quit":"\pCompleted - Click to quit");
  191.     
  192.     FlushEvents(everyEvent,0);
  193.     ValidRect(&logo->portRect);
  194.     for(;;)
  195.         {
  196.         EventRecord    ev;
  197.         
  198.         WaitNextEvent(everyEvent,&ev,60,nil);
  199.         if(ev.what==updateEvt) LogoUpdate();
  200.         if(ev.what==keyDown || ev.what==mouseDown) break;
  201.         }
  202.     }
  203. else if(chx==4)    // Repair System
  204.     {
  205.     FSSpec    fsp;
  206.     
  207.     FindFolder(kOnSystemDisk,kSystemFolderType,false,&fsp.vRefNum,&fsp.parID);
  208.     BlockMoveData(LMGetSysResName(),fsp.name,32);
  209.     
  210.     /* First scan the whole system folder for files of type INIT, ID 33, sig 'JS' */
  211.     
  212.     logo=GetNewDialog(257,nil,(WindowPtr)-1);
  213.     SetPort(logo);
  214.     ShowWindow(logo);
  215.     DrawDialog(logo);
  216.     
  217.     recurseNodeProc = CheckINITNodeProc;
  218.     recurseDirProc = nil;
  219.     
  220.     SetCursor(*GetCursor(watchCursor));
  221.     RecurseDirectory(fsp.vRefNum,fsp.parID);
  222.     InitCursor();
  223.     
  224.     DisposeDialog(logo);
  225.     
  226.     
  227.     if(numo)
  228.         {
  229.         NumToString(numo,volnm);
  230.         ParamText(volnm,numo==1?"\p was":"\ps were",nil,nil);
  231.         Alert(136,nil);
  232.         ExitToShell();
  233.         }
  234.     else
  235.         {
  236.         short    srf;
  237.         
  238.         prevent_moves = 1;
  239.         
  240.         /* Now call 'repair' on the system file itself. */
  241.         srf=LMGetSysMap();
  242.         UseResFile(srf);
  243.         numo=RepairApp(srf);
  244.         if(!numo && DamagedApp(srf)) numo=2;
  245.         UseResFile(orrez);
  246.         
  247.         prevent_moves = 0;
  248.         
  249.         GetIndString(prognosis,128,((numo+1)<<1) + (check_only?1:0) + 1);
  250.         ParamText(prognosis,nil,nil,nil);
  251.         Alert(135,nil);
  252.         
  253.         goto Rechoice;
  254.         }
  255.     }
  256. }
  257.  
  258. void LogoUpdate(void)
  259. {
  260. SetPort(logo);
  261. BeginUpdate(logo);
  262. DrawDialog(logo);
  263. EndUpdate(logo);
  264. }
  265.  
  266. void LogoRefresh(char saveco)
  267. {
  268. SetPort(logo);
  269. ParamText(saveco?"\pinfected":"\prepaired",nil,nil,nil);
  270. DrawDialog(logo);
  271. }
  272.  
  273. /* DirProc's return true if the directory should be processed. */
  274. /* AppProc's return true if the file should be processed again. */
  275.  
  276. void RecurseDirectory(short vref, long did)
  277. {
  278. HFileInfo    tpb;
  279. FSSpec        tana;
  280. short        idx,    i;
  281.  
  282. if(Button() || hit_but) {hit_but=1; return;}
  283.  
  284. lantana=&tana;
  285.  
  286. tana.vRefNum=vref;
  287. tana.parID=did;
  288.  
  289. tpb.ioCompletion=nil;
  290. tpb.ioNamePtr=tana.name;
  291. tpb.ioVRefNum=tana.vRefNum;
  292. for(idx=1;;idx++)
  293.     {
  294.     tpb.ioFDirIndex=idx;
  295.     tpb.ioDirID=tana.parID;
  296.     
  297.     PBGetCatInfoSync((CInfoPBRec*)&tpb);
  298.     if(tpb.ioResult) break;
  299.     
  300.     if(tpb.ioFlAttrib&ioDirMask)
  301.         {
  302.         if(recurseDirProc && !recurseDirProc()) continue;
  303.         
  304.         RecurseDirectory(vref,tpb.ioDirID);
  305.         lantana=&tana;
  306.         continue;
  307.         }
  308.     /* If the resource fork is already open it's probably us - and even
  309.     if it isn't we should be fiddling with running applications */
  310.     if(tpb.ioFlAttrib&0x04) continue;
  311.     
  312.     for(i=0;i<ntt;i++) if(tpb.ioFlFndrInfo.fdType==targType[i]) break;
  313.     if(i<ntt)
  314.         {
  315.         if(recurseNodeProc()) idx--;
  316.         }
  317.     }
  318. }
  319.  
  320. Boolean CheckAppDirProc(void)
  321. {
  322. if(!(upi&0xF))
  323.     {
  324.     EventRecord        ev;
  325.     
  326.     SetDialogItemText(dirnh,lantana->name);
  327.     GetNextEvent(everyEvent,&ev);
  328.     if(ev.what==updateEvt) LogoUpdate();
  329.     // other events are ignored
  330.     }
  331. upi++;
  332.  
  333. return true;
  334. }
  335.  
  336.  
  337. Boolean CheckAppNodeProc(void)
  338. {
  339. short    rrf;
  340. char    saveco,    reso;
  341.  
  342. saveco=check_only;
  343.  
  344. rrf=FSpOpenResFile(lantana,fsRdWrPerm);
  345. if(!rrf || rrf==-1)
  346.     {
  347.     rrf=FSpOpenResFile(lantana,fsRdPerm);
  348.     if(!rrf || rrf==-1) return false;
  349.     // file is locked
  350.     check_only=1;
  351.     }
  352.  
  353. reso=RepairApp(rrf);
  354. if(!reso && DamagedApp(rrf)) reso=2;
  355.  
  356. CloseResFile(rrf);
  357.  
  358. if(reso==-1)
  359.     {
  360.     ParamText(lantana->name,nil,nil,nil);
  361.     Alert(131,nil);
  362.     
  363.     if(logef)
  364.         {
  365.         WriteString(logef,"\p• Following file is irretrievably infected: ");
  366.         WriteAppPath();
  367.         }
  368.     
  369.     LogoRefresh(saveco);
  370.     }
  371. else if(reso==1)
  372.     {
  373.     if(!saveco && check_only)    // wanted to repair but file locked
  374.         {
  375.         ParamText(lantana->name,nil,nil,nil);
  376.         Alert(132,nil);
  377.         if(logef)
  378.             WriteString(logef,"\p• Following file is infected but was not repaired: ");
  379.         }
  380.     SetDialogItemText(filnh,lantana->name);
  381.     ufi=0;
  382.     numo++;
  383.     
  384.     if(logef) WriteAppPath();
  385.     
  386.     LogoRefresh(saveco);
  387.     }
  388. else if(reso==2)
  389.     {
  390.     uchar    *mipe;
  391.     
  392.     if(saveco) mipe="\p";
  393.     else if(check_only)    mipe="\p, but was not renamed as it is locked";
  394.     else mipe="\p, and has had '.bad' appended to its name";
  395.     
  396.     ParamText(lantana->name,mipe,nil,nil);
  397.     Alert(133,nil);
  398.     
  399.     if(logef)
  400.         {
  401.         WriteString(logef,"\p• Following file is irretrievably damaged: ");
  402.         WriteAppPath();
  403.         }
  404.     
  405.     LogoRefresh(saveco);
  406.     }
  407. /*
  408. else
  409.     {
  410.     // Well, the file is either clean or we got an unknown result code...
  411.     }
  412. */
  413.  
  414. toto++;
  415. check_only=saveco;
  416.  
  417. if(!(ufi&0xF))
  418.     {
  419.     NumToString(numo,nums);
  420.     SetDialogItemText(numh,nums);
  421.     NumToString(toto,tots);
  422.     SetDialogItemText(toth,tots);
  423.     }
  424. ufi++;
  425.  
  426. return false;
  427. }
  428.  
  429.  
  430. // Open lantana, and make sure it ain't got no nasty INIT 33 in it
  431. Boolean CheckINITNodeProc(void)
  432. {
  433. Handle    nasty;
  434. FSSpec    trashme;
  435. OSErr    lerr;
  436. short    rrf;
  437. Boolean    baddie;
  438.  
  439. rrf=FSpOpenResFile(lantana,fsRdPerm);    // check_only doesn't worry us here
  440. if(!rrf || rrf==-1) return false;
  441.  
  442. nasty=Get1Resource('INIT',33);
  443. baddie = ( nasty && ((short*)(*nasty))[4] == 'JS' );
  444. CloseResFile(rrf);
  445.  
  446. if(!baddie) return false;
  447.  
  448. lerr=-1;
  449. if(!check_only)
  450.     {
  451.     FindFolder(lantana->vRefNum,kTrashFolderType,true,&trashme.vRefNum,&trashme.parID);
  452.     // CatMove is an H function (like HOpen, etc.), and it's used here because
  453.     // it's easier than finding out the ID of the trash folder's parent.
  454.     // (Not always root ... on network vols it's a different hidden folder)
  455.     lerr=CatMove(lantana->vRefNum,lantana->parID,lantana->name,trashme.parID,"\p:");
  456.     }
  457.  
  458. InitCursor();
  459. ParamText(lantana->name,(check_only || lerr)?
  460.     "\pYou should delete it before you do anything else.":
  461.     "\pIt has been moved to the trash.",
  462.     nil,nil);
  463. Alert(134,nil);
  464. SetCursor(*GetCursor(watchCursor));
  465.  
  466. numo++;
  467.  
  468. return (lerr==0);    // process index again if we moved the file out so we don't miss one
  469. }
  470.  
  471.  
  472. /* Writes lantana's path to logef */
  473. void WriteAppPath(void)
  474. {
  475. HFileInfo    tpb;
  476. Str63        dina;
  477. long        *bsp;
  478.  
  479.  
  480. tpb.ioCompletion=nil;
  481. tpb.ioVRefNum=lantana->vRefNum;
  482. tpb.ioNamePtr=dina;
  483. tpb.ioFDirIndex=-1;
  484.  
  485. bsp=(long*)bigstak;        // 8000-deep folders? no problem :-)
  486. *bsp=lantana->parID;
  487.  
  488. while(*bsp!=fsRtDirID)
  489.     {
  490.     tpb.ioDirID=*bsp;
  491.     PBGetCatInfoSync((CInfoPBRec*)&tpb);
  492.     if(tpb.ioResult) break;
  493.     *(++bsp)=tpb.ioFlParID;
  494.     }
  495.  
  496. // It's too late tonight to figure out how to construct the pathname
  497. // backwards in the buffer. And this bit doesn't need to be fast.
  498.  
  499. WriteString(logef,volnm);
  500. WriteString(logef,"\p:");
  501. for(bsp--;bsp>=(long*)bigstak;bsp--)
  502.     {
  503.     tpb.ioDirID=*bsp;
  504.     PBGetCatInfoSync((CInfoPBRec*)&tpb);
  505.     
  506.     WriteString(logef,dina);
  507.     WriteString(logef,"\p:");
  508.     }
  509. WriteString(logef,lantana->name);
  510. WriteString(logef,"\p\r");
  511. }
  512.  
  513.  
  514. /* Yes, I know, I should've made it a dialog or put in more buttons or something */
  515. pascal Boolean AlertKludge(DialogPtr theDialog, EventRecord *theEvent, short *itemHit)
  516. {
  517. ControlHandle    abh,    bbh,    cbh;
  518. KeyMap            kk;
  519. Boolean            tobecheck;
  520.  
  521. GetKeys(kk);
  522. tobecheck = (kk[1]&0x8000)?1:0;
  523.  
  524. if(theEvent->what==keyDown && (theEvent->message&charCodeMask)==13)
  525.     {
  526.     GetDialogItem(theDialog,1,nil,(Handle*)&abh,nil);
  527.     HiliteControl(abh,1);
  528.     Delay(8,nil);
  529.     HiliteControl(abh,0);
  530.     
  531.     *itemHit=1;
  532.     return true;
  533.     }
  534.  
  535. if(theEvent->what==mouseDown) lmdco=check_only;
  536.  
  537. if(tobecheck==check_only) return false;
  538.  
  539. GetDialogItem(theDialog,2,nil,(Handle*)&abh,nil);
  540. GetDialogItem(theDialog,3,nil,(Handle*)&bbh,nil);
  541. GetDialogItem(theDialog,4,nil,(Handle*)&cbh,nil);
  542.  
  543. if(check_only=tobecheck)    // intentional single equal-sign!
  544.     {
  545.     SetControlTitle(abh,"\pExamine One File…");
  546.     SetControlTitle(bbh,"\pExamine All Volumes");
  547.     SetControlTitle(cbh,"\pExamine System");
  548.     }
  549. else
  550.     {
  551.     SetControlTitle(abh,"\pRepair One File…");
  552.     SetControlTitle(bbh,"\pRepair All Volumes");
  553.     SetControlTitle(cbh,"\pRepair System");
  554.     }
  555.  
  556. if(theEvent->what==mouseDown) lmdco=check_only;
  557.  
  558. return false;
  559. }
  560.  
  561.  
  562.  
  563. void DecodeVirus(void)
  564. {
  565. StandardFileReply    rep;
  566. Handle                org,    dst;
  567. short                rrf,    i;
  568.  
  569. StandardGetFile(nil,-1,nil,&rep);
  570. if(!rep.sfGood) ExitToShell();
  571.  
  572. rrf=FSpOpenResFile(&rep.sfFile,fsRdWrPerm);
  573. org=Get1Resource('INIT',33);
  574. HLock(org);
  575. dst=NewHandle(GetHandleSize(org));
  576. HLock(dst);
  577.  
  578. BlockMoveData(*org,*dst,GetHandleSize(org));
  579.  
  580. for(i=0x0A;i<0x6EE+0x0A;i++) (*dst)[i]^=0xCC;
  581.  
  582. HUnlock(dst);
  583. HUnlock(org);
  584.  
  585. AddResource(dst,'INIT',0,nil);
  586.  
  587. CloseResFile(rrf);
  588. }